package com.jsh.frame.myframe2.net.base;

import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;

import com.google.gson.Gson;
import com.jsh.frame.myframe2.manager.UserManager;
import com.jsh.frame.myframe2.utils.LogUtil;
import com.jsh.frame.myframe2.utils.StringUtil;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created by zhangyang on 2016/7/26.
 * <p/>
 * 网络接口的基类
 */
public class NetManager implements NetApi {
    private LogUtil logUtil = new LogUtil(getClass());

    private String url;//完整的地址

    private Map<String, String> params;//参数集

    private OkHttpClient mClient;

    private Gson mGson;

    private NetCallback callBack;

    private Handler handler;

    private Map<String, String> header = new HashMap<>();//请求头

    private Request.Builder builder;

    /**
     * @param urlDiff 不包括公共部分的地址部分
     */
    public NetManager(@NonNull String urlDiff, NetCallback callBack) {
//        init();
//        url = NET_BASE + urlDiff;
//        this.callBack = callBack;
//        handler = new Handler(Looper.getMainLooper());
        this(urlDiff, null, null, callBack);

    }

    /**
     * @param urlDiff 不包括公共部分的地址部分
     * @param params  参数集
     */
    public NetManager(@NonNull String urlDiff, Map<String, String> params, NetCallback callBack) {
//        init();
//        this.url = NET_BASE + urlDiff;
//        this.params = params;
//        this.callBack = callBack;
        this(urlDiff, params, null, callBack);
    }

    public NetManager(@NonNull String urlDiff, String token, NetCallback callBack) {
//        init();
        this(urlDiff, null, token, callBack);

    }

    public NetManager(@NonNull String urlDiff, Map<String, String> params, String token, NetCallback callBack) {
        init();
        String net_base;
        if (UserManager.getInstance().getUserModel() == null) {
            net_base = NetApi.NET_BASE;
        } else {
            net_base = UserManager.getInstance().getUserModel().getNET_BASE();
        }

        this.url = net_base + urlDiff;
        this.params = params;
        if (!StringUtil.isEmpty(token)) {
            header.put("token", token);
        }

        this.callBack = callBack;

    }

    private void init() {
        this.mClient = new OkHttpClient();
        handler = new Handler(Looper.getMainLooper());
        mGson = new Gson();
        builder = new Request.Builder();
    }

    private void addRequestHeader(Request.Builder builder) {
        if (header != null && header.size() > 0) {
            Set<String> keySet = header.keySet();
            for (String key : keySet) {
                builder.addHeader(key, header.get(key));
            }
        }
    }

    public void get() {
        builder.url(buildGetUrl());
        addRequestHeader(builder);
        Call call = mClient.newCall(builder.build());
//        Request request = new Request.Builder().url(buildGetUrl()).build();
//        Call call = mClient.newCall(request);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                sendFailedStringCallback(request, e, callBack);
            }

            @Override
            public void onResponse(Response response) throws IOException {
                try {
                    final String string = response.body().string();
                    if (callBack.mType == String.class) {
                        sendSuccessResultCallback(string, callBack);
                    } else {
                        Object o = mGson.fromJson(string, callBack.mType);
                        sendSuccessResultCallback(o, callBack);
                    }
                } catch (IOException e) {
                    sendFailedStringCallback(response.request(), e, callBack);
                } catch (com.google.gson.JsonParseException e) {//Json解析的错误
                    logUtil.i("Json解析的错误 " + e.toString());
                    sendFailedStringCallback(response.request(), e, callBack);
                }
            }
        });
    }

    public void post() {
        builder.url(url).post(buildPostBody());
        addRequestHeader(builder);
        Call call = mClient.newCall(builder.build());
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                sendFailedStringCallback(request, e, callBack);
            }

            @Override
            public void onResponse(Response response) throws IOException {
                try {
                    final String string = response.body().string();
                    if (callBack.mType == String.class) {
                        sendSuccessResultCallback(string, callBack);
                    } else {
                        Object o = mGson.fromJson(string, callBack.mType);
                        sendSuccessResultCallback(o, callBack);
                    }


                } catch (IOException e) {
                    sendFailedStringCallback(response.request(), e, callBack);
                } catch (com.google.gson.JsonParseException e) {//Json解析的错误
                    sendFailedStringCallback(response.request(), e, callBack);
                }
            }
        });
    }

    //上传json
    public void postJsonAsync(String json) {
        builder.url(url).post(buildPostJsonBody(json));
        addRequestHeader(builder);
        Call call = mClient.newCall(builder.build());
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                sendFailedStringCallback(request, e, callBack);
            }

            @Override
            public void onResponse(Response response) throws IOException {
                if (response.code() != 200) {
                    sendFailedStringCallback(response.request(), new Exception("操作失败"), callBack);
                    logUtil.d("连接错误" + response.code());
                    return;
                }
                try {
                    final String string = response.body().string();
                    if (callBack.mType == String.class) {
                        sendSuccessResultCallback(string, callBack);
                    } else {
                        Object o = mGson.fromJson(string, callBack.mType);
                        sendSuccessResultCallback(o, callBack);
                    }


                } catch (IOException e) {
                    sendFailedStringCallback(response.request(), e, callBack);
                } catch (com.google.gson.JsonParseException e) {//Json解析的错误
                    sendFailedStringCallback(response.request(), new Exception("数据解析失败"), callBack);
                }
            }
        });
    }


    private RequestBody buildPostBody() {
        FormEncodingBuilder builder = new FormEncodingBuilder();
        if (params == null || params.size() == 0) {
            logUtil.i("requestUrl--->" + url);
            return builder.build();
        } else {
            Set<String> keySet = params.keySet();
            for (String key : keySet) {
                builder.add(key, params.get(key));
            }
            logUtil.d("params--->" + url + params.toString());
            return builder.build();
        }
    }

    private RequestBody buildPostJsonBody(String json) {
        RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        logUtil.i("requestUrl--->" + url);
        logUtil.json(json);
        return body;
    }


    private void sendSuccessResultCallback(final Object response, final NetCallback callback) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (callback != null)
                    callback.onResponse(response);

                String r = mGson.toJson(response);
                logUtil.json(r);

            }
        });
    }

    private void sendFailedStringCallback(final Request request, final Exception e, final NetCallback callback) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (callback != null)
                    callback.onError(request.urlString(), e);
            }
        });
    }

    private String buildGetUrl() {
        if (params == null || params.size() == 0) {
            logUtil.i("requestUrl--->" + url);
            return url;

        } else {
            StringBuffer sb = new StringBuffer(url);
            Set<String> keySet = params.keySet();
            sb.append("?");
            for (String key : keySet) {
                sb.append(key).append("=").append(params.get(key)).append("&");
            }
            String str = sb.toString();
            if (str.substring(str.length() - 1, str.length()).equals("&")) {
                sb.delete(sb.length() - 1, sb.length());
            }
            logUtil.i("requestUrl--->" + sb.toString());
            return sb.toString();

        }
    }


}
